package vip.liux.contracts.infrastructure.pay.dto.order;


import lombok.Data;
import lombok.experimental.Accessors;
import vip.liux.contracts.infrastructure.pay.PayClientException;
import vip.liux.contracts.infrastructure.pay.PayOrderDisplayModeEnum;
import vip.liux.contracts.shared.enums.pay.PayOrderStatus;

import java.time.LocalDateTime;

/**
 * 渠道支付订单 Response Dto
 *
 * @author 芋道源码
 */
@Data
@Accessors(chain = true)
public class ClientPayOrderDto {

    /**
     * 支付状态
     * <p>
     * 枚举：{@link PayOrderStatus}
     */
    private Integer status;

    /**
     * 外部订单号
     * <p>
     * 对应 PayOrderExtensionDO 的 no 字段
     */
    private String outTradeNo;

    /**
     * 支付渠道编号
     */
    private String channelOrderNo;
    /**
     * 支付渠道用户编号
     */
    private String channelUserId;

    /**
     * 支付成功时间
     */
    private LocalDateTime successTime;

    /**
     * 原始的同步/异步通知结果
     */
    private Object rawData;

    // ========== 主动发起支付时，会返回的字段 ==========

    /**
     * 展示模式
     * <p>
     * 枚举 {@link PayOrderDisplayModeEnum} 类
     */
    private String displayMode;
    /**
     * 展示内容
     */
    private String displayContent;

    /**
     * 调用渠道的错误码
     * <p>
     * 注意：这里返回的是业务异常，而是不系统异常。
     * 如果是系统异常，则会抛出 {@link PayClientException}
     */
    private String channelErrorCode;
    /**
     * 调用渠道报错时，错误信息
     */
    private String channelErrorMsg;

    public ClientPayOrderDto() {
    }

    /**
     * 创建【WAITING】状态的订单返回
     */
    public static ClientPayOrderDto waitingOf(String displayMode, String displayContent,
                                              String outTradeNo, Object rawData) {
        ClientPayOrderDto respDto = new ClientPayOrderDto();
        respDto.status = PayOrderStatus.WAITING.getValue();
        respDto.displayMode = displayMode;
        respDto.displayContent = displayContent;
        // 相对通用的字段
        respDto.outTradeNo = outTradeNo;
        respDto.rawData = rawData;
        return respDto;
    }

    /**
     * 创建【SUCCESS】状态的订单返回
     */
    public static ClientPayOrderDto successOf(String channelOrderNo, String channelUserId, LocalDateTime successTime,
                                              String outTradeNo, Object rawData) {
        ClientPayOrderDto respDto = new ClientPayOrderDto();
        respDto.status = PayOrderStatus.SUCCESS.getValue();
        respDto.channelOrderNo = channelOrderNo;
        respDto.channelUserId = channelUserId;
        respDto.successTime = successTime;
        // 相对通用的字段
        respDto.outTradeNo = outTradeNo;
        respDto.rawData = rawData;
        return respDto;
    }

    /**
     * 创建指定状态的订单返回，适合支付渠道回调时
     */
    public static ClientPayOrderDto of(Integer status, String channelOrderNo, String channelUserId, LocalDateTime successTime,
                                       String outTradeNo, Object rawData) {
        ClientPayOrderDto respDto = new ClientPayOrderDto();
        respDto.status = status;
        respDto.channelOrderNo = channelOrderNo;
        respDto.channelUserId = channelUserId;
        respDto.successTime = successTime;
        // 相对通用的字段
        respDto.outTradeNo = outTradeNo;
        respDto.rawData = rawData;
        return respDto;
    }

    /**
     * 创建【CLOSED】状态的订单返回，适合调用支付渠道失败时
     */
    public static ClientPayOrderDto closedOf(String channelErrorCode, String channelErrorMsg,
                                             String outTradeNo, Object rawData) {
        ClientPayOrderDto respDto = new ClientPayOrderDto();
        respDto.status = PayOrderStatus.CLOSED.getValue();
        respDto.channelErrorCode = channelErrorCode;
        respDto.channelErrorMsg = channelErrorMsg;
        // 相对通用的字段
        respDto.outTradeNo = outTradeNo;
        respDto.rawData = rawData;
        return respDto;
    }

}
